package com.zdgk.core.control.read.modbus;

import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.serial.SerialParameters;
import com.intelligt.modbus.jlibmodbus.serial.SerialPort;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import com.zdgk.core.control.config.ControlConfigInfo;
import com.zdgk.core.control.forward.modbus.ModbusSlaveConfig;
import com.zdgk.core.control.read.modbus.cache.DeviceRegisterCache;
import com.zdgk.core.control.read.modbus.cache.DeviceRegisterCacheResult;
import com.zdgk.core.control.read.modbus.thread.ModbusThread;
import com.zdgk.core.mqtt.MqttClientConfig;
import com.zdgk.core.web.service.ConfigService;
import com.zdgk.core.web.service.RuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.net.InetAddress;

@Slf4j
@Configuration
public class ModbusMasterConfig implements DisposableBean {

    private ModbusMaster master;
    private ModbusThread modbusThread;
    private Thread thread;
    @Resource
    private MqttClientConfig mqttClientConfig;
    @Resource
    private ConfigService configService;
    @Resource
    private RuleService ruleService;

    @Resource
    private ModbusSlaveConfig modbusSlaveConfig;

    private ControlConfigInfo controlConfigInfo;

    @PostConstruct
    public void init() {
        try {
            selfPortsList();
            controlConfigInfo = configService.getControlKey();
            //初始化缓存输入寄存器
            DeviceRegisterCache.buildInputRegisterInfo(controlConfigInfo.getServerAddressArr(), controlConfigInfo.getReadStartAddress(), controlConfigInfo.getQuantity());
            //初始化缓存保持寄存器
            DeviceRegisterCache.buildKeepRegisterInfo(controlConfigInfo.getServerAddressArr(), controlConfigInfo.getKeepReadStartAddress(), controlConfigInfo.getKeepQuantity());
            //载入解析规则
            DeviceRegisterCacheResult.readRule(controlConfigInfo.getServerAddressArr(), ruleService);
            if (openMaster()) {
                modbusThread = new ModbusThread(master, controlConfigInfo, mqttClientConfig,modbusSlaveConfig);
                thread = new Thread(modbusThread, "modbus-rtu-thread");
                thread.start();
            }
        } catch (Exception e) {
            log.error("Modbus 启动失败");
        }
    }

    private void selfPortsList() {
        try{
            com.fazecast.jSerialComm.SerialPort[] commPorts = com.fazecast.jSerialComm.SerialPort.getCommPorts();
            for (int i = 0; i < commPorts.length; i++) {
                com.fazecast.jSerialComm.SerialPort port = commPorts[i];
                log.info("串口【{}】",port.getSystemPortName());
            }
        }catch (Exception e){
            log.error("串口列出失败，{}",e.getMessage());
        }


    }

    private boolean openMaster() {
        try {
            if (master != null && master.isConnected()) {
                master.disconnect();
                master = null;
            }
            if(thread!=null){
                thread.interrupt();
                thread = null;
            }
            if ("serial".equals(controlConfigInfo.getMode())) {
                SerialParameters params = new SerialParameters();
                params.setDevice(controlConfigInfo.getName()); // 串口名称
                params.setBaudRate(SerialPort.BaudRate.getBaudRate(controlConfigInfo.getBaudRate())); // 波特率
                params.setDataBits(8); // 数据位
                params.setStopBits(1); // 停止位
                params.setParity(SerialPort.Parity.getParity(0)); // 无校验
                master = ModbusMasterFactory.createModbusMasterRTU(params);
                master.setResponseTimeout(3000);
                master.connect();
                if (!master.isConnected()) {
                    log.error("Modbus-Rtu-Master【{}】启动失败", controlConfigInfo.getName());
                } else {
                    log.info("Modbus-Rtu-Master【{}】启动成功", controlConfigInfo.getName());
                    return true;
                }
            } else {
                TcpParameters params = new TcpParameters();
                params.setHost(InetAddress.getByName(controlConfigInfo.getHost()));
                params.setPort(controlConfigInfo.getPort());
                params.setKeepAlive(true);
                master = ModbusMasterFactory.createModbusMasterTCP(params);
                Modbus.setAutoIncrementTransactionId(true);
                master.connect();
                if (!master.isConnected()) {
                    log.error("Modbus-Tcp-Master【{}】:{}启动失败", controlConfigInfo.getHost(), controlConfigInfo.getPort());
                } else {
                    log.info("Modbus-Tcp-Master【{}】:{}启动成功", controlConfigInfo.getHost(), controlConfigInfo.getPort());
                    return true;
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return false;

    }

    @Override
    public void destroy() throws Exception {
        if (modbusThread != null) {
            modbusThread.stop();
        }
        master.disconnect();
    }

    public boolean isConnected() {
        return master != null && master.isConnected();
    }
}
